﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading.Tasks;
using System.Diagnostics;
using WxLib.Core.Serializers;
using WxLib.Core.Util;
using WxLib.Core.Cache;
using WxLib.Core.Exceptions;
using WxLib.Core.RequestHandlers;

namespace WxLib.QRCode.RequestHandlers
{
    /// <summary>
    /// 使用缓存处理请求。
    /// </summary>
    public class CachedRequestHandler : ICachedRequestHandler
    {
        private readonly TraceSource _trace = new TraceSource("WxLib", SourceLevels.All);

        /// <summary>
        /// 无参构造函数
        /// </summary>
        public CachedRequestHandler() { }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serializer"></param>
        /// <param name="cache"></param>
        /// <param name="cacheLevel"></param>
        public CachedRequestHandler(ISerializer serializer, IWxLibCache cache, CacheLevel cacheLevel)
        {
            this.Serializer = serializer;
            this.Cache = cache;
            this.CacheLevel = cacheLevel;
        }

        /// <summary>
        ///  获取或设置缓存
        /// </summary>
        public IWxLibCache Cache { get; set; }

        /// <summary>
        ///  获取或设置缓存级别
        /// </summary>
        /// <value>The cache level.</value>
        public CacheLevel CacheLevel { get; set; }

        /// <summary>
        /// 获取或设置序列化程序
        /// </summary>
        public ISerializer Serializer { get; set; }

        /// <summary>
        ///  从uri请求数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="uri"></param>
        /// <returns></returns>
        public async Task<T> RequestAsync<T>(Uri uri)
        {
            string data = null;
            if (CacheLevel == CacheLevel.Default || CacheLevel == CacheLevel.CacheOnly)
                data = await Cache.LoadAsync(uri).ConfigureAwait(false);
            var cached = data != null;
            if (cached) return Serializer.Deserialize<T>(data);
            if (CacheLevel == CacheLevel.CacheOnly) return default(T);
            try
            {
                var response = await HttpRequestHelper.GetResponseAsync(HttpRequestHelper.CreateRequest(uri)).ConfigureAwait(false);
                data = await HttpRequestHelper.GetResponseContentAsync(response);

            }
            catch (WebException e)
            {
                throw new WxLibWebException("A request caused a WebException.", e.InnerException as WebException);
            }
            var xml = Serializer.Deserialize<T>(data);
            if (CacheLevel == CacheLevel.Default || CacheLevel == CacheLevel.Refresh)
                await Cache.StoreAsync(uri, getCacheExpirationTime(xml), data).ConfigureAwait(false);
            return xml;
        }

        /// <summary>
        /// 获取对象的过期时间设置
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        private DateTime getCacheExpirationTime(dynamic xml)
        {
            //if (o.GetType().Is) throw new System.Exception("Should never occur.");
            return DateTime.Now;// xml.CachedUntil;
        }
    }
}
